﻿using CoreWCF.IdentityModel.Policy;
using CoreWCF.Channels;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;

namespace CoreWCF.Security
{
    public class SecurityMessageProperty : IMessageProperty, IDisposable
    {
        //// This is the list of outgoing supporting tokens
        //Collection<SupportingTokenSpecification> outgoingSupportingTokens;
        //Collection<SupportingTokenSpecification> incomingSupportingTokens;
        SecurityTokenSpecification transportToken;
        //SecurityTokenSpecification protectionToken;
        //SecurityTokenSpecification initiatorToken;
        //SecurityTokenSpecification recipientToken;

        ServiceSecurityContext securityContext;

        //string senderIdPrefix = "_";
        bool disposed = false;

        public SecurityMessageProperty()
        {
            securityContext = ServiceSecurityContext.Anonymous;
        }

        public ServiceSecurityContext ServiceSecurityContext
        {
            get
            {
                ThrowIfDisposed();
                return securityContext;
            }
            set
            {
                ThrowIfDisposed();
                securityContext = value;
            }
        }

        public ReadOnlyCollection<IAuthorizationPolicy> ExternalAuthorizationPolicies { get; set; }

        //public SecurityTokenSpecification ProtectionToken
        //{
        //    get
        //    {
        //        ThrowIfDisposed();
        //        return this.protectionToken;
        //    }
        //    set
        //    {
        //        ThrowIfDisposed();
        //        this.protectionToken = value;
        //    }
        //}

        //public SecurityTokenSpecification InitiatorToken
        //{
        //    get
        //    {
        //        ThrowIfDisposed();
        //        return this.initiatorToken;
        //    }
        //    set
        //    {
        //        ThrowIfDisposed();
        //        this.initiatorToken = value;
        //    }
        //}

        //public SecurityTokenSpecification RecipientToken
        //{
        //    get
        //    {
        //        ThrowIfDisposed();
        //        return this.recipientToken;
        //    }
        //    set
        //    {
        //        ThrowIfDisposed();
        //        this.recipientToken = value;
        //    }
        //}

        public SecurityTokenSpecification TransportToken
        {
            get
            {
                ThrowIfDisposed();
                return transportToken;
            }
            set
            {
                ThrowIfDisposed();
                transportToken = value;
            }
        }


        //public string SenderIdPrefix
        //{
        //    get
        //    {
        //        return this.senderIdPrefix;
        //    }
        //    set
        //    {
        //        XmlHelper.ValidateIdPrefix(value);
        //        this.senderIdPrefix = value;
        //    }
        //}

        //public bool HasIncomingSupportingTokens
        //{
        //    get
        //    {
        //        ThrowIfDisposed();
        //        return ((this.incomingSupportingTokens != null) && (this.incomingSupportingTokens.Count > 0));
        //    }
        //}

        //public Collection<SupportingTokenSpecification> IncomingSupportingTokens
        //{
        //    get
        //    {
        //        ThrowIfDisposed();
        //        if (this.incomingSupportingTokens == null)
        //        {
        //            this.incomingSupportingTokens = new Collection<SupportingTokenSpecification>();
        //        }
        //        return this.incomingSupportingTokens;
        //    }
        //}

        //public Collection<SupportingTokenSpecification> OutgoingSupportingTokens
        //{
        //    get
        //    {
        //        if (this.outgoingSupportingTokens == null)
        //        {
        //            this.outgoingSupportingTokens = new Collection<SupportingTokenSpecification>();
        //        }
        //        return this.outgoingSupportingTokens;
        //    }
        //}

        //internal bool HasOutgoingSupportingTokens
        //{
        //    get
        //    {
        //        return ((this.outgoingSupportingTokens != null) && (this.outgoingSupportingTokens.Count > 0));
        //    }
        //}

        public IMessageProperty CreateCopy()
        {
            ThrowIfDisposed();
            SecurityMessageProperty result = new SecurityMessageProperty();

        //    if (this.HasOutgoingSupportingTokens)
        //    {
        //        for (int i = 0; i < this.outgoingSupportingTokens.Count; ++i)
        //        {
        //            result.OutgoingSupportingTokens.Add(this.outgoingSupportingTokens[i]);
        //        }
        //    }

        //    if (this.HasIncomingSupportingTokens)
        //    {
        //        for (int i = 0; i < this.incomingSupportingTokens.Count; ++i)
        //        {
        //            result.IncomingSupportingTokens.Add(this.incomingSupportingTokens[i]);
        //        }
        //    }

            result.securityContext = securityContext;
        //    result.externalAuthorizationPolicies = this.externalAuthorizationPolicies;
        //    result.senderIdPrefix = this.senderIdPrefix;

        //    result.protectionToken = this.protectionToken;
        //    result.initiatorToken = this.initiatorToken;
        //    result.recipientToken = this.recipientToken;
            result.transportToken = transportToken;

            return result;
        }

        public static SecurityMessageProperty GetOrCreate(Message message)
        {
            if (message == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(message));

            SecurityMessageProperty result = null;
            if (message.Properties != null)
                result = message.Properties.Security;

            if (result == null)
            {
                result = new SecurityMessageProperty();
                message.Properties.Security = result;
            }

            return result;
        }

        //void AddAuthorizationPolicies(SecurityTokenSpecification spec, Collection<IAuthorizationPolicy> policies)
        //{
        //    if (spec != null && spec.SecurityTokenPolicies != null && spec.SecurityTokenPolicies.Count > 0)
        //    {
        //        for (int i = 0; i < spec.SecurityTokenPolicies.Count; ++i)
        //        {
        //            policies.Add(spec.SecurityTokenPolicies[i]);
        //        }
        //    }
        //}

        //internal ReadOnlyCollection<IAuthorizationPolicy> GetInitiatorTokenAuthorizationPolicies()
        //{
        //    return GetInitiatorTokenAuthorizationPolicies(true);
        //}

        //internal ReadOnlyCollection<IAuthorizationPolicy> GetInitiatorTokenAuthorizationPolicies(bool includeTransportToken)
        //{
        //    return GetInitiatorTokenAuthorizationPolicies(includeTransportToken, null);
        //}

        //internal ReadOnlyCollection<IAuthorizationPolicy> GetInitiatorTokenAuthorizationPolicies(bool includeTransportToken, SecurityContextSecurityToken supportingSessionTokenToExclude)
        //{
        //    // fast path
        //    if (!this.HasIncomingSupportingTokens)
        //    {
        //        if (this.transportToken != null && this.initiatorToken == null && this.protectionToken == null)
        //        {
        //            if (includeTransportToken && this.transportToken.SecurityTokenPolicies != null)
        //            {
        //                return this.transportToken.SecurityTokenPolicies;
        //            }
        //            else
        //            {
        //                return EmptyReadOnlyCollection<IAuthorizationPolicy>.Instance;
        //            }
        //        }
        //        else if (this.transportToken == null && this.initiatorToken != null && this.protectionToken == null)
        //        {
        //            return this.initiatorToken.SecurityTokenPolicies ?? EmptyReadOnlyCollection<IAuthorizationPolicy>.Instance;
        //        }
        //        else if (this.transportToken == null && this.initiatorToken == null && this.protectionToken != null)
        //        {
        //            return this.protectionToken.SecurityTokenPolicies ?? EmptyReadOnlyCollection<IAuthorizationPolicy>.Instance;
        //        }
        //    }

        //    Collection<IAuthorizationPolicy> policies = new Collection<IAuthorizationPolicy>();
        //    if (includeTransportToken)
        //    {
        //        AddAuthorizationPolicies(this.transportToken, policies);
        //    }
        //    AddAuthorizationPolicies(this.initiatorToken, policies);
        //    AddAuthorizationPolicies(this.protectionToken, policies);
        //    if (this.HasIncomingSupportingTokens)
        //    {
        //        for (int i = 0; i < this.incomingSupportingTokens.Count; ++i)
        //        {
        //            if (supportingSessionTokenToExclude != null)
        //            {
        //                SecurityContextSecurityToken sct = this.incomingSupportingTokens[i].SecurityToken as SecurityContextSecurityToken;
        //                if (sct != null && sct.ContextId == supportingSessionTokenToExclude.ContextId)
        //                {
        //                    continue;
        //                }
        //            }
        //            SecurityTokenAttachmentMode attachmentMode = this.incomingSupportingTokens[i].SecurityTokenAttachmentMode;
        //            // a safety net in case more attachment modes get added to the product without 
        //            // reviewing this code.
        //            if (attachmentMode == SecurityTokenAttachmentMode.Endorsing
        //                || attachmentMode == SecurityTokenAttachmentMode.Signed
        //                || attachmentMode == SecurityTokenAttachmentMode.SignedEncrypted
        //                || attachmentMode == SecurityTokenAttachmentMode.SignedEndorsing)
        //            {
        //                AddAuthorizationPolicies(this.incomingSupportingTokens[i], policies);
        //            }
        //        }
        //    }
        //    return new ReadOnlyCollection<IAuthorizationPolicy>(policies);
        //}

        public void Dispose()
        {
            // do no-op for future V2
            if (!disposed)
            {
                disposed = true;
            }
        }

        void ThrowIfDisposed()
        {
            if (disposed)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ObjectDisposedException(GetType().FullName));
            }
        }
    }

}
